/**
 * @file bl0906.h
 * @brief bl0906(六相交流电能计量芯片)驱动
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2020-10-21
 * @copyright Copyright (c) 2020  烽火通信
 */
#ifndef __BL0906_H
#define __BL0906_H 
#include "project_config.h"

#if DRV_BL0906_EN
#include "bl0906_config.h"
#include "bsp_uart_v2.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"


/* BL0906单相6路充电桩模式对应寄存器地址 */
#define Addr_1_WAVE             0x02
#define Addr_2_WAVE             0x03
#define	Addr_3_WAVE             0x04
#define	Addr_4_WAV              0x05
#define	Addr_5_WAVE             0x08
#define	Addr_6_WAVE             0x09
#define	Addr_V_WAVE_            0x0B

#define Addr_1_RMS              0x0D
#define Addr_2_RMS              0x0E
#define Addr_3_RMS              0x0F
#define Addr_4_RMS              0x10
#define Addr_5_RMS              0x13
#define Addr_6_RMS              0x14
#define Addr_V_RMS_             0x16

#define Addr_1_FAST_RMS         0x18
#define Addr_2_FAST_RMS         0x19
#define Addr_3_FAST_RMS         0x1A
#define Addr_4_FAST_RMS         0x1B
#define Addr_5_FAST_RMS         0x1E
#define Addr_6_FAST_RMS         0x1F
#define Addr_V_FAST_RMS         0x21

#define Addr_WATT1              0x23
#define Addr_WATT2              0x24
#define Addr_WATT3              0x25
#define Addr_WATT4              0x26
#define Addr_WATT5              0x29
#define Addr_WATT6              0x2A
#define Addr_WATT               0x2C
#define Addr_VAR                0x2D
#define Addr_VA                 0x2E

#define Addr_CF1_CNT            0x30
#define Addr_CF2_CNT            0x31
#define Addr_CF3_CNT            0x32
#define Addr_CF4_CNT            0x33
#define Addr_CF5_CNT            0x36
#define Addr_CF6_CNT            0x37
#define Addr_CF_CNT             0x39
#define Addr_CFQ_CNT            0x3A
#define Addr_CFS_CNT            0x3B

#define Addr_ANGLE1             0x3D
#define Addr_ANGLE2             0x3E
#define Addr_ANGLE3             0x3F
#define Addr_ANGLE4             0x40
#define Addr_ANGLE5             0x43
#define Addr_ANGLE6             0x44

#define Addr_1_FAST_RMS_HOLD    0x47
#define Addr_2_FAST_RMS_HOLD    0x48
#define Addr_3_FAST_RMS_HOLD    0x49
#define Addr_PF                 0x4A
#define Addr_LINE_WATTHR        0x4B
#define Addr_LINE_VARHR         0x4C
#define Addr_SIGN               0x4D
#define Addr_PERIOD             0x4E

#define Addr_STATUS1            0x54
#define Addr_STATUS3            0x56
#define Addr_4_FAST_RMS_HOLD    0x57
#define Addr_5_FAST_RMS_HOLD    0x5A
#define Addr_6_FAST_RMS_HOLD    0x5B

#define Addr_VAR1               0x5D    ///< 可选通道（全波）无功功率	
#define Addr_TPS1_           	0x5E

/* 用户操作寄存器 */
#define Addr_GAIN1              0x60
#define Addr_GAIN2              0x61
    
#define Addr_PHASE1             0x64
#define Addr_PHASE2_3           0x65
#define Addr_PHASE4             0x66
#define Addr_PHASE5             0x67
#define Addr_PHASE6             0x68
#define Addr_PHASEV             0x69
#define Addr_VAR_PHCAL_I        0x6A
#define Addr_VAR_PHCAL_V        0x6B

#define Addr_RMSGN1             0x6D
#define Addr_RMSGN2             0x6E
#define Addr_RMSGN3             0x6F
#define Addr_RMSGN4             0x70
#define Addr_RMSGN5             0x73
#define Addr_RMSGN6             0x74
#define Addr_RMSGNV             0x76

#define Addr_RMSOS1             0x78
#define Addr_RMSOS2             0x79
#define Addr_RMSOS3             0x7A
#define Addr_RMSOS4             0x7B
#define Addr_RMSOS5             0x7E
#define Addr_RMSOS6             0x7F
#define Addr_RMSOSV             0x81
#define Addr_WA_LOS1            0x82
#define Addr_WA_LOS2_3          0x83
#define Addr_WA_LOS4            0x84
#define Addr_WA_LOS5            0x85
#define Addr_WA_LOS6            0x86
#define Addr_VAR_LOS            0x87
#define Addr_VAR_WATT_CREEP     0x88
#define Addr_WA_CREEP2          0x89
#define	Addr_RMS_CREEP          0x8A
#define Addr_FAST_RMS_CTRL      0x8B
#define Addr_I_V_PKLVL          0x8C

#define Addr_SAGCYC_ZXTOUT      0x8E
#define Addr_SAGLVL_LINECYC     0x8F
#define Addr_FLAG_CTRL          0x90
#define Addr_FLAG_CTRL1         0x91
#define Addr_FLAG_CTRL2         0x92
#define Addr_ADC_PD             0x93
#define Addr_MODE1              0x96
#define Addr_MODE2              0x97
#define Addr_MODE3              0x98

#define Addr_MASK1              0x9A
#define Addr_MASK2              0x9B

#define Addr_RST_ENG            0x9D
#define Addr_USR_WRPROT_        0x9E
#define Addr_SOFT_RESET_        0x9F

/* 校表寄存器，OTP保存 */
#define Addr_CHGN1              0xA1
#define Addr_CHGN2              0xA2
#define Addr_CHGN3              0xA3
#define Addr_CHGN4              0xA4
#define Addr_CHGN5              0xA7
#define Addr_CHGN6              0xA8
#define Addr_CHGNV              0xAA
#define Addr_CHOS1              0xAC
#define Addr_CHOS2              0xAD
#define Addr_CHOS3              0xAE
#define Addr_CHOS4              0xAF
#define Addr_CHOS5              0xB2
#define Addr_CHOS6              0xB3
#define Addr_CHOSV              0xB5
#define Addr_WATTGN1            0xB7
#define Addr_WATTGN2            0xB8
#define Addr_WATTGN3            0xB9
#define Addr_WATTGN4            0xBA
#define Addr_WATTGN5            0xBD
#define Addr_WATTGN6            0xBE

#define Addr_WATTOS1            0xC1
#define Addr_WATTOS2            0xC2
#define Addr_WATTOS3            0xC3
#define Addr_WATTOS4            0xC4
#define Addr_WATTOS5            0xC7
#define Addr_WATTOS6            0xC8
#define Addr_VARGN              0xCA
#define Addr_VAROS              0xCB
#define Addr_VAGN               0xCC
#define Addr_VAOS               0xCD
#define Addr_CFDIV              0xCE

/* BL0906报警电平控制 */
#define BL_M1_EN            ( 1 << 1 )      ///< 1 通道
#define BL_M2_EN            ( 1 << 2 )      ///< 2 通道
#define BL_M3_EN            ( 1 << 3 )      ///< 3 通道
#define BL_M4_EN            ( 1 << 4 )      ///< 4 通道
#define BL_M5_EN            ( 1 << 7 )      ///< 5 通道
#define BL_M6_EN            ( 1 << 8 )      ///< 6 通道

/* 电参数读取选项，可多项或组合 */
#define BL0906_ELECT_V      ( 1 << 0 )      ///< 读电压有效值
#define BL0906_ELECT_PERIOD ( 1 << 1 )      ///< 读工频

#define BL0906_ELECT_I_1    ( 1 << 2 )      ///< 读电流有效值
#define BL0906_ELECT_I_2    ( 1 << 3 )
#define BL0906_ELECT_I_3    ( 1 << 4 )
#define BL0906_ELECT_I_4    ( 1 << 5 )
#define BL0906_ELECT_I_5    ( 1 << 6 )
#define BL0906_ELECT_I_6    ( 1 << 7 )

#define BL0906_ELECT_P_1    ( 1 << 8 )      ///< 读有功功率
#define BL0906_ELECT_P_2    ( 1 << 9 )
#define BL0906_ELECT_P_3    ( 1 << 10 )
#define BL0906_ELECT_P_4    ( 1 << 11 )
#define BL0906_ELECT_P_5    ( 1 << 12 )
#define BL0906_ELECT_P_6    ( 1 << 13 )

#define BL0906_ELECT_L_1    ( 1 << 14 )     ///< 读快速有效值（漏电流）
#define BL0906_ELECT_L_2    ( 1 << 15 )
#define BL0906_ELECT_L_3    ( 1 << 16 )
#define BL0906_ELECT_L_4    ( 1 << 17 )
#define BL0906_ELECT_L_5    ( 1 << 18 )
#define BL0906_ELECT_L_6    ( 1 << 19 )

#define BL0906_ELECT_I_ALL  0xFC            ///< 读所有通道有效电流
#define BL0906_ELECT_P_ALL  0x3F00          ///< 读所有通道有功功率
#define BL0906_ELECT_ALL    0xFFFFFFFF      ///< 读全部电参数

/**
 * @brief BL0906电参数结构体
 */
typedef struct Bl0906_Elect_s
{
#if BL0906_ELECT_USE_FLOAT  /* 使用浮点运算 */

#if BL0906_1_RMS_EN
    float RMS_1;        ///< 1通道电流有效值 0.001A
#endif
#if BL0906_2_RMS_EN
    float RMS_2;        ///< 2通道电流有效值 0.001A
#endif
#if BL0906_3_RMS_EN
    float RMS_3;        ///< 3通道电流有效值 0.001A
#endif
#if BL0906_4_RMS_EN
    float RMS_4;        ///< 4通道电流有效值 0.001A
#endif
#if BL0906_5_RMS_EN
    float RMS_5;        ///< 5通道电流有效值 0.001A
#endif
#if BL0906_6_RMS_EN
    float RMS_6;        ///< 6通道电流有效值 0.001A
#endif
#if BL0906_V_RMS_EN
    float RMS_V;        ///< 电压有效值 0.1V
#endif
#if BL0906_1_FAST_RMS_EN
    float FAST_RMS_1;   ///< 1通道电流快速有效值 0.001A
#endif
#if BL0906_2_FAST_RMS_EN
    float FAST_RMS_2;   ///< 2通道电流快速有效值 0.001A
#endif
#if BL0906_3_FAST_RMS_EN
    float FAST_RMS_3;   ///< 3通道电流快速有效值 0.001A
#endif
#if BL0906_4_FAST_RMS_EN
    float FAST_RMS_4;   ///< 4通道电流快速有效值 0.001A
#endif
#if BL0906_5_FAST_RMS_EN
    float FAST_RMS_5;   ///< 5通道电流快速有效值 0.001A
#endif
#if BL0906_6_FAST_RMS_EN
    float FAST_RMS_6;   ///< 6通道电流快速有效值 0.001A
#endif
#if BL0906_WATT1_EN
    float WATT_1;       ///< 1通道有功功率 0.1W
#endif
#if BL0906_WATT2_EN
    float WATT_2;       ///< 2通道有功功率 0.1W
#endif
#if BL0906_WATT3_EN
    float WATT_3;       ///< 3通道有功功率 0.1W
#endif
#if BL0906_WATT4_EN
    float WATT_4;       ///< 4通道有功功率 0.1W
#endif
#if BL0906_WATT5_EN
    float WATT_5;       ///< 5通道有功功率 0.1W
#endif
#if BL0906_WATT6_EN
    float WATT_6;       ///< 6通道有功功率 0.1W
#endif
#if BL0906_PERIOD_EN
    float Period;       ///< 线电压频率 0.1Hz
#endif

#else   /* 使用整形计算 */
#if BL0906_1_RMS_EN
    uint32_t RMS_1;         ///<  XX.XXX A 0.001安/LSB
#endif
#if BL0906_2_RMS_EN
    uint32_t RMS_2;
#endif
#if BL0906_3_RMS_EN
    uint32_t RMS_3;
#endif
#if BL0906_4_RMS_EN
    uint32_t RMS_4;
#endif
#if BL0906_5_RMS_EN
    uint32_t RMS_5;
#endif
#if BL0906_6_RMS_EN
    uint32_t RMS_6;
#endif
#if BL0906_V_RMS_EN
    uint32_t RMS_V;         ///<  XXX.X	V 0.1伏/LSB
#endif
#if BL0906_1_FAST_RMS_EN
    uint32_t FAST_RMS_1;    ///<  XX.XXX A 0.001安/LSB
#endif
#if BL0906_2_FAST_RMS_EN
    uint32_t FAST_RMS_2;
#endif
#if BL0906_3_FAST_RMS_EN
    uint32_t FAST_RMS_3;
#endif
#if BL0906_4_FAST_RMS_EN
    uint32_t FAST_RMS_4;
#endif
#if BL0906_5_FAST_RMS_EN
    uint32_t FAST_RMS_5;
#endif
#if BL0906_6_FAST_RMS_EN
    uint32_t FAST_RMS_6;
#endif
#if BL0906_WATT1_EN
    uint32_t WATT_1;        ///<  XXXX.X W 0.1瓦/LSB
#endif
#if BL0906_WATT2_EN
    uint32_t WATT_2;
#endif
#if BL0906_WATT3_EN
    uint32_t WATT_3;
#endif
#if BL0906_WATT4_EN
    uint32_t WATT_4;
#endif
#if BL0906_WATT5_EN
    uint32_t WATT_5;
#endif
#if BL0906_WATT6_EN
    uint32_t WATT_6;
#endif
#if BL0906_PERIOD_EN
    uint32_t Period;        ///< XX.XX Hz 0.01Hz/LSB
#endif
#endif
} Bl0906_Elect_t;


/** @brief 统计电量结构体 */
typedef struct Bl0906_Energy_s
{
#if BL0906_ENERGY_USE_FLOAT /* 能量使用浮点运算 */

#if BL0906_CF1_EN
    float Energy_1;         ///< 1通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF2_EN
    float Energy_2;         ///< 2通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF3_EN
    float Energy_3;         ///< 3通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF4_EN
    float Energy_4;         ///< 4通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF5_EN
    float Energy_5;         ///< 5通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF6_EN
    float Energy_6;         ///< 6通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF_EN
    float Energy_Sum;       ///< 实际总用电量，0.001千瓦小时
#endif

#else   /* 能量使用整形运算 */

#if BL0906_CF1_EN
    uint32_t Energy_1;      ///< 1通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF2_EN
    uint32_t Energy_2;      ///< 2通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF3_EN
    uint32_t Energy_3;      ///< 3通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF4_EN
    uint32_t Energy_4;      ///< 4通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF5_EN
    uint32_t Energy_5;      ///< 5通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF6_EN
    uint32_t Energy_6;      ///< 6通道的实际用电量，0.001千瓦小时
#endif
#if BL0906_CF_EN
    uint32_t Energy_Sum;    ///< 实际总用电量，0.001千瓦小时
#endif

#endif
} Bl0906_Energy_t;

#if !(BL0906_ENERGY_USE_FLOAT && BL0906_CF_CLR_SEL)
/** @brief 统计电量中间变量余数结构体 */
typedef struct Bl0906_EnergyMid_s
{
#if BL0906_ENERGY_USE_FLOAT

#if BL0906_CF1_EN
    float EnergyMid_1;      ///< 1通道电量寄存器清零保存
#endif
#if BL0906_CF2_EN
    float EnergyMid_2;      ///< 2通道电量寄存器清零保存
#endif
#if BL0906_CF3_EN
    float EnergyMid_3;      ///< 3通道电量寄存器清零保存
#endif
#if BL0906_CF4_EN
    float EnergyMid_4;      ///< 4通道电量寄存器清零保存
#endif
#if BL0906_CF5_EN
    float EnergyMid_5;      ///< 5通道电量寄存器清零保存
#endif
#if BL0906_CF6_EN
    float EnergyMid_6;      ///< 6通道电量寄存器清零保存
#endif
#if BL0906_CF_EN
    float EnergyMid_Sum;    ///< 总电量寄存器计算清零保存
#endif

#else

#if BL0906_CF1_EN
    uint32_t EnergyMid_1;   ///< 1通道电量寄存器余数
#endif
#if BL0906_CF2_EN
    uint32_t EnergyMid_2;   ///< 2通道电量寄存器余数
#endif
#if BL0906_CF3_EN
    uint32_t EnergyMid_3;   ///< 3通道电量寄存器余数
#endif
#if BL0906_CF4_EN
    uint32_t EnergyMid_4;   ///< 4通道电量寄存器余数
#endif
#if BL0906_CF5_EN
    uint32_t EnergyMid_5;   ///< 5通道电量寄存器余数
#endif
#if BL0906_CF6_EN
    uint32_t EnergyMid_6;   ///< 6通道电量寄存器余数
#endif
#if BL0906_CF_EN
    uint32_t EnergyMid_Sum; ///< 总电量寄存器计算余数
#endif

#endif
} Bl0906_EnergyMid_t;
#endif

/**
 * @brief BL0906对象结构体
 */
typedef struct Bl0906_s
{
    UartId_t UartId;        ///< 使用的串口编号
    bool IsInitialized;     ///< 是否初始化

#if BL0906_ELECT_USE_FLOAT
    float Current_K;        ///< 电流A转换系数
    float L_Current_K;      ///< 漏电流A转换系数
    float Voltage_K;        ///< 电压转换系数
    float Power_K;          ///< 通道A功率转换系数
#else
    uint32_t Current_K;     ///< 电流A转换系数
    uint32_t L_Current_K;   ///< 漏电流A转换系数
    uint32_t Voltage_K;     ///< 电压转换系数
    uint32_t Power_K;       ///< 通道A功率转换系数
#endif

#if BL0906_ENERGY_USE_FLOAT
    float Energy_K;         ///< 1度电对应的脉冲数
#else
    uint32_t Energy_K;      ///< 1度电对应的脉冲数
#endif

    Bl0906_Energy_t Energy; ///< 实际用电量
#if !(BL0906_ENERGY_USE_FLOAT && BL0906_CF_CLR_SEL)
    Bl0906_EnergyMid_t EnergyMid;   ///< 电量寄存器余数
#endif

    TimerHandle_t bl_timer; ///< 电量统计计时器
    SemaphoreHandle_t Energy_lock;  ///< 电量读写锁
    SemaphoreHandle_t WR_lock;      ///< 通信锁

    uint8_t resume_times;   ///< 自恢复次数
} Bl0906_t;

/**
 * @brief Bl0906初始化
 * @param  obj         Bl0906对象
 * @param  uartId      串口编号
 * @param  tx          串口TX引脚
 * @param  rx          串口RX引脚
 * @return uint8_t SUCCESS：成功
 */
int8_t Bl0906_Init( Bl0906_t *obj, UartId_t uartId, PinNames tx, PinNames rx );

/**
 * @brief Bl0906去初始化
 * @param  obj         Bl0906对象
 */
void Bl0906_DeInit( Bl0906_t *obj );

/**
 * @brief Bl0906软件复位
 * @param  obj         Bl0906对象
 * @param  Rst_Type    复位类型，0：系统复位，1：寄存器复位
 */
void Bl0906_SoftRst( Bl0906_t *obj, uint8_t	Rst_Type );

/**
 * @brief BL0906报警输出手动控制
 * @param[in]  obj      Bl0906对象
 * @param[in]  mask     BL_Mx_EN的组合（BL_M1_EN|BL_M2_EN）
 * @param[in]  en       电平
 * @return int8_t 
 * - @b Sucess :  \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 * - @ref BSP_ERROR @ref BSP_ERROR_CHECK
 * @par 示例:
 * @code
 *    Bl0906_SetMn( obj, BL_M1_EN | BL_M2_EN | BL_M5_EN, ture );
 * @endcode
 */
int8_t Bl0906_SetMn( Bl0906_t *obj, uint16_t mask, bool en );

/**
 * @brief Bl0906设置电量值
 * @param[in]  obj      Bl0906对象
 * @param[in]  Energy   各通道电量值及总电量值设置
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 */
int8_t Bl0906_SetEnergy( Bl0906_t *obj, Bl0906_Energy_t *Energy );

/**
 * @brief Bl0906获取电量值
 * @param[in]  obj      Bl0906对象
 * @param[in]  Energy   统计的电量信息结构体
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 */
int8_t Bl0906_GetEnergy( Bl0906_t *obj, Bl0906_Energy_t *Energy );

/**
 * @brief 获取电量瞬时参数
 * @param[in]  obj      Bl0906对象
 * @param[in]  Elect    电参数信息
 * @param[in]  mask     电参数选项掩码
 * @return int8_t 
 * - @b Sucess : BSP_SUCCESS \n
 * - @b Fail
 * - @ref BSP_ERROR_INVALID_PARAM - 非法入参
 * - @ref BSP_ERROR_NO_INIT - 未初始化
 * - 其他寄存器读取错误
 * @par 示例:
 * @code
 *    Bl0906_GetElect( obj, Elect, BL0906_ELECT_P_ALL );
 *    Bl0906_GetElect( obj, Elect, BL0906_ELECT_V | BL0906_ELECT_I_1 );
 * @endcode
 */
int8_t Bl0906_GetElect( Bl0906_t *obj, Bl0906_Elect_t *Elect, uint32_t mask );

#endif  /* BL0906_EN */

#endif	 // __BL0906_H 

/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/
